/// <reference path="../typings/requirejs/require.d.ts"/>
/// <reference path="../typings/googlemaps/google.maps.d.ts"/>

module Trust.Maps {

    export interface IMapHandler {
        isLoading: boolean;
        zoom: IZoomActions;
        position: IMapPosition;
        markers: IMarkerActions;
    }

    export interface IMapPosition {
        setCenter(data: Trust.Casas.Model.IPositionData): void;
        getCenter(): Trust.Casas.Model.IPositionData;
    }

    export interface IZoomActions {
        goIn(): void;
        goOut(): void;
        goTo(toValue: number): void;
        current(): number;
    }

    export class MarkerData {
        //constructor(latitude: number, longitude: number, draggable: boolean = false) {
        //    this.position = {
        //        latitude: latitude,
        //        longitude: longitude
        //    };
        //    this.draggable = (draggable === true) || false;
        //}
        position: Trust.Casas.Model.IPositionData;
        autoUpdate: boolean = true;
        draggable: boolean;
        title: string;
        text: string;
        events: {
            click?: (data: MarkerData) => void;
            dragStart?: (data: MarkerData) => void;
            dragging?: (data: MarkerData) => void;
            dragEnd?: (data: MarkerData) => void;
        } = {}
    }

    export interface IMarkerActions {
        add(data: MarkerData): void;
        all(): MarkerData[];
    }

    export class MapOptions {
        initialPosition: Trust.Casas.Model.IPositionData = { latitude: 0, longitude: 0 };
        zoom: number = 15;
    }

    // Class
    class GoogleMapHandler implements IMapHandler {
        private holder: Element;
        private map: google.maps.Map;

        public zoom: IZoomActions;
        public position: IMapPosition;
        public markers: IMarkerActions;
        public isLoading: boolean;

        constructor(holder: Element, data: MapOptions) {
            this.holder = holder;

            var mapData: google.maps.MapOptions = {
                zoom: data.zoom,
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                center: new google.maps.LatLng(data.initialPosition.latitude, data.initialPosition.longitude)
            };
            this.map = new google.maps.Map(holder, mapData);

            this.zoom = {
                goIn: function () {
                    this.map.setZoom(this.map.getZoom() + 1);
                },
                goOut: function () {
                    this.map.setZoom(this.map.getZoom() - 1);
                },
                goTo: function (zoomValue: number) {
                    this.map.setZoom(zoomValue);
                },
                current: function () {
                    return this.map.getZoom();
                }
            };

            this.position = {
                setCenter: function (position: Trust.Casas.Model.IPositionData) {
                    if (position)
                        this.map.setCenter(new google.maps.LatLng(position.latitude, position.longitude, false));
                },
                getCenter: function () {
                    var result = this.map.getCenter();
                    return { latitude: result.lat(), longitude: result.lng() };
                }
            }

            this.markers = {
                all: () => {
                    return currentMarkers;
                },
                add: (data) => {

                    var contentString = '<div class="info-content-holder">' + data.text + '</div>';
                    var infowindow: google.maps.InfoWindow = new google.maps.InfoWindow({
                        content: contentString
                    });

                    var marker: google.maps.Marker = new google.maps.Marker({
                        map: this.map,
                        position: new google.maps.LatLng(data.position.latitude, data.position.longitude),
                        draggable: data.draggable,
                        animation: google.maps.Animation.DROP,
                        title: data.title
                    });

                    marker.addListener('click', function () {
                        infowindow.open(this.map, this);
                        if (data.events.click) {
                            data.events.click(data);
                        }
                    });

                    if (data.draggable === true) {
                        marker.addListener('dragend', function () {
                            if (data.autoUpdate === true) {
                                data.position.latitude = marker.getPosition().lat();
                                data.position.longitude = marker.getPosition().lng();
                            }
                            if (data.events.dragEnd)
                                data.events.dragEnd(data);
                        });
                    }
                    currentMarkers.push(marker);
                }
            }

            var currentMarkers: Array = new Array();

        }
    }

    export class MapHandlerFactory {
        static create = function (ele: Element, options?: MapOptions): IMapHandler {
            return new GoogleMapHandler(ele, options || new MapOptions());
        }
    }
}